package com.huawei.esdk.tp.business.professional.confmgr;

import java.util.Date;
import java.util.List;
import javax.xml.datatype.XMLGregorianCalendar;
import com.huawei.esdk.platform.common.SDKErrorCode;
import com.huawei.esdk.platform.common.SDKResult;
import com.huawei.esdk.platform.common.config.ConfigManager;
import com.huawei.esdk.platform.common.exception.SDKException;
import com.huawei.esdk.platform.common.utils.DateUtils;
import com.huawei.esdk.platform.common.utils.NumberUtils;
import com.huawei.esdk.platform.common.utils.StringUtils;
import com.huawei.esdk.tp.base.BaseService;
import com.huawei.esdk.tp.common.ErrInfo;
import com.huawei.esdk.tp.domain.model.AdhocConference;
import com.huawei.esdk.tp.domain.model.CDRInformation;
import com.huawei.esdk.tp.domain.model.Conference;
import com.huawei.esdk.tp.domain.model.HoldingConference;
import com.huawei.esdk.tp.domain.model.PeriodicalConference;
import com.huawei.esdk.tp.domain.model.ScheduleConference;
import com.huawei.esdk.tp.domain.model.Site;
import com.huawei.esdk.tp.domain.model.SiteInConference;
import com.huawei.esdk.tp.domain.model.bean.AdhocConfFreeBusyStateList;
import com.huawei.esdk.tp.domain.model.bean.AdhocConferencesList;
import com.huawei.esdk.tp.domain.model.bean.ContinuousPresenceCapability;
import com.huawei.esdk.tp.domain.model.bean.ContinuousPresenceParam;
import com.huawei.esdk.tp.domain.model.bean.DateTimeRange;
import com.huawei.esdk.tp.domain.model.bean.MultiPointCDRQueryConfig;
import com.huawei.esdk.tp.domain.model.bean.MultiPointCDRResult;
import com.huawei.esdk.tp.domain.model.bean.PagedList;
import com.huawei.esdk.tp.domain.model.bean.PointToPointCDR;
import com.huawei.esdk.tp.domain.model.bean.PointToPointCDRQueryConfig;
import com.huawei.esdk.tp.domain.model.bean.QuerySites;
import com.huawei.esdk.tp.domain.model.bean.SiteFreeBusyRes;
import com.huawei.esdk.tp.domain.model.bean.SiteMCU;

public class ConfManagerService extends BaseService
{
    public SDKErrorCode connectSites(String confId, List<String> siteUris)
        throws SDKException
    {
        SDKErrorCode errorCode = new SDKErrorCode();
        if (StringUtils.isEmpty(confId))
        {
            errorCode.setErrCode(ErrInfo.CONF_ID_ISNULL_ERRORCODE);
        }
        else if (!StringUtils.isUintNumber(confId))
        {
            errorCode.setErrCode(ErrInfo.CONF_ID_IS_INVALID_ERRORCODE);
        }
        else if (null == siteUris || 0 == siteUris.size())
        {
            errorCode.setErrCode(ErrInfo.SITE_URI_ISNULL_ERRORCODE);
        }
        else
        {
            ScheduleConference conf = new ScheduleConference(confId);
            errorCode = conf.connectSites(siteUris);
        }
        return errorCode;
    }
    
    public SDKErrorCode disconnectSites(String confId, List<String> siteUris)
        throws SDKException
    {
        SDKErrorCode errorCode = new SDKErrorCode();
        if (StringUtils.isEmpty(confId))
        {
            errorCode.setErrCode(ErrInfo.CONF_ID_ISNULL_ERRORCODE);
        }
        else if (!StringUtils.isUintNumber(confId))
        {
            errorCode.setErrCode(ErrInfo.CONF_ID_IS_INVALID_ERRORCODE);
        }
        else if (null == siteUris || 0 == siteUris.size())
        {
            errorCode.setErrCode(ErrInfo.SITE_URI_ISNULL_ERRORCODE);
        }
        else
        {
            ScheduleConference conf = new ScheduleConference(confId);
            errorCode = conf.disconnectSites(siteUris);
        }
        return errorCode;
    }
    
    public SDKErrorCode delScheduledConf(String confId, XMLGregorianCalendar beginTime)
        throws SDKException
    {
        SDKErrorCode errorCode = new SDKErrorCode();
        if (StringUtils.isEmpty(confId))
        {
            errorCode.setErrCode(ErrInfo.CONF_ID_ISNULL_ERRORCODE);
        }
        else if (!StringUtils.isUintNumber(confId))
        {
            errorCode.setErrCode(ErrInfo.CONF_ID_IS_INVALID_ERRORCODE);
        }
        else
        {
            Conference conf = new Conference(confId);
            conf.setBeginTime(DateUtils.toDate(beginTime));
            errorCode = conf.deleteConference();
        }
        return errorCode;
    }
    
    /**
     * 预约普通会议 解耦service，默认值，组合接口，消息校验都在这里处理
     * @throws SDKException 
     */
    public SDKResult<ScheduleConference> scheduleConfResponseService(ScheduleConference conference)
        throws SDKException
    {
        // 不用校验必填，默认值，所有的判断都由产品完成
        SDKResult<ScheduleConference> result = new SDKResult<ScheduleConference>();
        if (!StringUtils.isEmpty(conference.getId()) && !StringUtils.isUintNumber(conference.getId()))
        {
            result.setErrCode(ErrInfo.CONF_ID_IS_INVALID_ERRORCODE);
            return result;
        }
        
        //R3修改,开放预留字段
        //        //增加一个对siteType的校验，当siteType为1，对已siteType_Auto的时候，返回0x22009004
        //        List<SiteInConference> siteInConferences = conference.getSites();
        //        for (SiteInConference siteInConference : siteInConferences)
        //        {
        //            if (null != siteInConference && ("SITE_TYPE_AUTO").equals(siteInConference.getSiteType()))
        //            {
        //                result.setErrCode(ErrInfo.PARAM_IS_RESERVE_ERRORCODE);
        //                return result;
        //            }
        //        }
        
        // 准备Model
        ScheduleConference scheduleConference = new ScheduleConference();
        result = scheduleConference.schedule(conference);
        
        return result;
    }
    
    /**
     * 修改会议 解耦service，默认值，组合接口，消息校验都在这里处理
     * @throws SDKException 
     */
    public SDKResult<ScheduleConference> editScheduleConfResponseService(ScheduleConference conference)
        throws SDKException
    {
        // 不用校验必填，默认值，所有的判断都由产品完成
        SDKResult<ScheduleConference> result = new SDKResult<ScheduleConference>();
        //增加一个对siteType的校验，当siteType为1，对已siteType_Auto的时候，返回0x22009004
        if (!StringUtils.isUintNumber(conference.getId()))
        {
            result.setErrCode(ErrInfo.CONF_ID_IS_INVALID_ERRORCODE);
            return result;
        }
        
        //R3修改,开放预留字段
        //        List<SiteInConference> siteInConferences = conference.getSites();
        //        for (SiteInConference siteInConference : siteInConferences)
        //        {
        //            if (null != siteInConference && ("SITE_TYPE_AUTO").equals(siteInConference.getSiteType()))
        //            {
        //                result.setErrCode(ErrInfo.PARAM_IS_RESERVE_ERRORCODE);
        //                return result;
        //            }
        //        }
        
        // 准备Model
        ScheduleConference scheduleConference = new ScheduleConference();
        result = scheduleConference.reschedule(conference);
        
        return result;
    }
    
    // //////////////////////////
    /**
     * 预约普通会议 解耦service，默认值，组合接口，消息校验都在这里处理
     * @throws SDKException 
     */
    public SDKResult<PeriodicalConference> scheduleRecurrenceConfResponseService(PeriodicalConference conference)
        throws SDKException
    {
        // 不用校验必填，默认值，所有的判断都由产品完成
        SDKResult<PeriodicalConference> result = new SDKResult<PeriodicalConference>();
        //增加一个对siteType的校验，当siteType为1，对已siteType_Auto的时候，返回0x22009004
        if (!StringUtils.isEmpty(conference.getId()) && !StringUtils.isUintNumber(conference.getId()))
        {
            result.setErrCode(ErrInfo.CONF_ID_IS_INVALID_ERRORCODE);
            return result;
        }
        
        //R3修改,开放预留字段
        //        List<SiteInConference> siteInConferences = conference.getSites();
        //        for (SiteInConference siteInConference : siteInConferences)
        //        {
        //            if (null != siteInConference && ("SITE_TYPE_AUTO").equals(siteInConference.getSiteType()))
        //            {
        //                result.setErrCode(ErrInfo.PARAM_IS_RESERVE_ERRORCODE);
        //                return result;
        //            }
        //        }
        // 准备Model
        PeriodicalConference scheduleConference = new PeriodicalConference();
        result = scheduleConference.scheduleRecurrence(conference);
        
        return result;
    }
    
    /**
     * 修改会议 解耦service，默认值，组合接口，消息校验都在这里处理
     * @param date 
     * @throws SDKException 
     */
    public SDKResult<PeriodicalConference> editScheduleRecurrenceConfResponseService(PeriodicalConference conference,
        Date date)
        throws SDKException
    {
        // 不用校验必填，默认值，所有的判断都由产品完成
        SDKResult<PeriodicalConference> result = new SDKResult<PeriodicalConference>();
        if (!StringUtils.isUintNumber(conference.getId()))
        {
            result.setErrCode(ErrInfo.CONF_ID_IS_INVALID_ERRORCODE);
            return result;
        }
        
        // R5C00适配，与TP OA保持一致，编辑周期会议需要增加子会议开始时间
        conference.setSubConfStartTime(date);
        // 准备Model
        PeriodicalConference scheduleConference = new PeriodicalConference();
        result = scheduleConference.rescheduleRecurrence(conference);
        
        return result;
    }
    
    public SDKResult<PagedList<Site>> querySites()
        throws SDKException
    {
        int totalNumber =
            NumberUtils.parseIntValue(ConfigManager.getInstance().getValue("professional.queryAllSites.totalNumber"));
        QuerySites querySites = new QuerySites();
        querySites.setCurrentPage(1);
        querySites.setNumberPerPage(totalNumber);
        return Site.querySites(querySites);
    }
    
    /**
     * 延长已预约或正在召开的普通会议或周期性会议
     * 
     * @param confId 会议ID
     * @param beginDate 会议开始时间 - 对周期会议中的单个会议进行修改。  * -
     *        如果是普通会议，或者对周期会议的所有会议进行修改，则可以不用输入。
     * @param prolongTime 准备延长的时间
     * 
     * @return 0如果成功否则非0
     * @throws SDKException 
     */
    public SDKErrorCode prolongScheduledConf(String confId, Date beginDate, Integer prolongTime)
        throws SDKException
    {
        SDKErrorCode errorCode;
        
        int validationResult = validateProlongConfParam(confId, beginDate, prolongTime);
        if (0 != validationResult)
        {
            errorCode = new SDKErrorCode();
            errorCode.setErrCode(validationResult);
            return errorCode;
        }
        
        // 准备Model
        ScheduleConference scheduleConference = new ScheduleConference();
        scheduleConference.setBeginTime(beginDate);
        errorCode = scheduleConference.prolong(confId, beginDate, prolongTime);
        
        return errorCode;
    }
    
    private int validateProlongConfParam(String confId, Date beginDate, Integer prolongTime)
    {
        if (StringUtils.isEmpty(confId) || null == prolongTime)
        {
            // 必填参数不全
            return ErrInfo.SDK_PARAM_NOT_COMPLETE_ERRORCODE;
        }
        if (!StringUtils.isUintNumber(confId))
        {
            return ErrInfo.CONF_ID_IS_INVALID_ERRORCODE;
        }
        
        // No need do the confId's corresponding conference existing validation
        // as SMC will do the checking.
        
        return 0;
    }
    
    public SDKResult<List<Site>> querySiteStatus(List<String> siteUris, DateTimeRange timeRange)
        throws SDKException
    {
        SDKResult<List<Site>> result = new SDKResult<List<Site>>();
        if (null == siteUris || 0 == siteUris.size())
        {
            result.setErrCode(ErrInfo.SITE_URI_ISNULL_ERRORCODE);
            return result;
        }
        
        if (null == timeRange)
        {
            result.setErrCode(ErrInfo.SDK_PARAM_NOT_COMPLETE_ERRORCODE);
            return result;
        }
        
        Site site = new Site();
        SiteFreeBusyRes response = site.querySiteFreeBusy(siteUris, timeRange);
        
        result.setErrCode(response.getResult().getErrCode());
        if (0 == result.getErrCode())
        {
            List<Site> siteList = response.getSiteFreeBusyStateList();
            result.setResult(siteList);
        }
        return result;
    }
    
    public SDKResult<List<Site>> synchSiteStatus(List<String> siteUris, DateTimeRange timeRange)
        throws SDKException
    {
        SDKResult<List<Site>> result = new SDKResult<List<Site>>();
        if (null == siteUris)
        {
            result.setErrCode(ErrInfo.SITE_URI_ISNULL_ERRORCODE);
            return result;
        }
        
        Site site = new Site();
        SiteFreeBusyRes response = site.synchSiteFreeBusy(siteUris, timeRange);
        
        result.setErrCode(response.getResult().getErrCode());
        if (0 == result.getErrCode())
        {
            result.setResult(response.getSiteFreeBusyStateList());
        }
        return result;
    }
    
    public SDKResult<List<Conference>> queryConferencesStatus(List<String> confIds)
        throws SDKException
    {
        SDKResult<List<Conference>> result = new SDKResult<List<Conference>>();
        
        for (String confId : confIds)
        {
            if (StringUtils.isEmpty(confId))
            {
                result.setErrCode(ErrInfo.CONF_ID_ISNULL_ERRORCODE);
                return result;
            }
            if (!StringUtils.isUintNumber(confId))
            {
                result.setErrCode(ErrInfo.CONF_ID_IS_INVALID_ERRORCODE);
                return result;
            }
        }
        result = Conference.queryConferencesStatus(confIds);
        
        return result;
    }
    
    public SDKResult<List<SiteInConference>> queryConfSitesStatus(String confId, List<String> siteUris)
        throws SDKException
    {
        SDKResult<List<SiteInConference>> result = new SDKResult<List<SiteInConference>>();
        if (StringUtils.isEmpty(confId))
        {
            result.setErrCode(ErrInfo.CONF_ID_ISNULL_ERRORCODE);
            return result;
        }
        if (!StringUtils.isUintNumber(confId))
        {
            result.setErrCode(ErrInfo.CONF_ID_IS_INVALID_ERRORCODE);
            return result;
        }
        
        SiteInConference siteInConference = new SiteInConference();
        siteInConference.setConfId(confId);
        result = siteInConference.querySitesStatusInConference(siteUris);
        return result;
    }
    
    public SDKErrorCode delSiteFromConfEx(String confId, String siteUri, Date beginTime)
        throws SDKException
    {
        SDKErrorCode errorCode = new SDKErrorCode();
        
        if (StringUtils.isEmpty(confId))
        {
            errorCode.setErrCode(ErrInfo.CONF_ID_ISNULL_ERRORCODE);
            return errorCode;
        }
        if (StringUtils.isEmpty(siteUri))
        {
            errorCode.setErrCode(ErrInfo.SITE_URI_ISNULL_ERRORCODE);
            return errorCode;
        }
        if (!StringUtils.isUintNumber(confId))
        {
            errorCode.setErrCode(ErrInfo.CONF_ID_IS_INVALID_ERRORCODE);
            return errorCode;
        }
        
        // 准备Model Bean
        ScheduleConference scheduleConference = new ScheduleConference(confId);
        SiteInConference site = new SiteInConference();
        site.setUri(siteUri);
        site.setBeginTime(beginTime);
        
        // 调用Model
        SDKErrorCode result = scheduleConference.removeSite(site);
        
        return result;
    }
    
    /**
     * 向已预约会议添加会场
     * 
     * @param confId
     * @param siteInfo
     * @param beginTime
     * @return
     * @throws SDKException 
     */
    public SDKResult<List<SiteInConference>> addSiteToConfEx(String confId, Site site, XMLGregorianCalendar date)
        throws SDKException
    {
        SDKResult<List<SiteInConference>> result = new SDKResult<List<SiteInConference>>();
        int retCode = validateConid(confId, site);
        if (0 != retCode)
        {
            result.setErrCode(retCode);
            return result;
        }
        
        //R3修改,开放预留字段
        //        if (PropertiesUtils.getValue("professional.addSiteToConfImpl.type").equals(site.getSiteType()))
        //        {
        //            result.setErrCode(ErrInfo.PARAM_IS_RESERVE_ERRORCODE);
        //            return result;
        //        }
        // 准备Model
        ScheduleConference conference = new ScheduleConference(confId);
        conference.setBeginTime(DateUtils.toDate(date));
        // 调用Model
        SDKResult<ScheduleConference> scResponse =
            conference.addSite(site,
                Boolean.parseBoolean(ConfigManager.getInstance().getValue("professional.site.IsUseAnonymousSite")));
        
        result.setErrCode(scResponse.getErrCode());
        if (0 == result.getErrCode())
        {
            result.setResult(scResponse.getResult().getSites());
        }
        return result;
    }
    
    private int validateConid(String confId, Site site)
    {
        if (StringUtils.isEmpty(confId) || null == site)
        {
            // 必填参数不全
            return ErrInfo.SDK_PARAM_NOT_COMPLETE_ERRORCODE;
        }
        // 校验参数类型
        if (!StringUtils.isUintNumber(confId))
        {
            // 参数类型错误
            return ErrInfo.CONF_ID_IS_INVALID_ERRORCODE;
        }
        return 0;
    }
    
    public SDKResult<AdhocConfFreeBusyStateList> queryAdhocConfFreeBusyEx(Integer duration, Date beginTime,
        List<String> confAccessCodes)
        throws SDKException
    {
        return AdhocConference.queryAdhocConfFreeBusyEx(duration, beginTime, confAccessCodes);
    }
    
    public SDKResult<PagedList<PointToPointCDR>> queryPointToPointCDR(PointToPointCDRQueryConfig queryConfig)
        throws SDKException
    {
        return CDRInformation.queryPointToPointCDR(queryConfig);
    }
    
    public SDKResult<MultiPointCDRResult> queryMultiPointCDREx(MultiPointCDRQueryConfig queryConfig)
        throws SDKException
    {
        return CDRInformation.queryMultiPointCDREx(queryConfig);
    }
    
    public SDKResult<AdhocConfFreeBusyStateList> synchAdhocConfFreeBusyEx(Integer duration, Date beginTime,
        List<String> confAccessCodes)
        throws SDKException
    {
        return AdhocConference.synchAdhocConfFreeBusyEx(duration, beginTime, confAccessCodes);
    }
    
    public SDKResult<AdhocConferencesList> queryAdhocConferencesEx(QuerySites querySites)
        throws SDKException
    {
        return AdhocConference.queryAdhocConferencesEx(querySites);
    }
    
    public SDKResult<ContinuousPresenceCapability> getContinuousPresenceInfoEx(String confId)
        throws SDKException
    {
        HoldingConference holdingConference = new HoldingConference(confId);
        return holdingConference.getContinuousPresenceInfoEx();
    }
    
    public SDKResult<ContinuousPresenceParam> getContinuousPresenceParamEx(String confId, String target)
        throws SDKException
    {
        HoldingConference holdingConference = new HoldingConference(confId);
        return holdingConference.getContinuousPresenceParamEx(target);
    }
    
    public SDKResult<List<SiteMCU>> queryConfSiteMCUEx(String confId, 
        List<String> siteUris, Date date)
        throws SDKException
    {
        SDKResult<List<SiteMCU>> result = null;
        if (!StringUtils.isUintNumber(confId))
        {
            result = new SDKResult<List<SiteMCU>>();
            result.setErrCode(ErrInfo.CONF_ID_IS_INVALID_ERRORCODE);
            return result;
        }
        
        // 准备Model
        ScheduleConference scheduleConference = new ScheduleConference();
        result = scheduleConference.queryConfSiteMCUEx(confId, siteUris, date);
        return result;
    }
}
